package com.yuw.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Date;

import org.junit.Test;

public class TestDriver {

	/**
	 * 反射工具类：Method类
	 */
	@Test
	public void test03() {
		// 获取Student类的Class实例对象
		Class<Student> clazz = Student.class;
		try {
			// 创建一个Student对象的实例
			Student stu0 = clazz.newInstance();
			stu0.setStuName("张三");
			// 获取Method工具类
			// 第一个参数是方法名，第二个参数是该方法对应的形参类型的列表
			Method method = clazz.getDeclaredMethod("doStuding", new Class[] { Date.class, String.class });
			// 使用Method类中的invoke方法，通过反射机制执行获取的方法对象
			/*
			 * invoke方法使用时，第一个参数是反射机制通过哪个实例对象去执行这个方法对象；
			 * 第二个是一个变长参数，需要和获取Method对象时所指定的形参列表保持对应关系； 返回值是方法对象执行的结果
			 */
			Object obj = method.invoke(stu0, new Object[] { new Date(), "天津西青" });
			System.out.println("反射执行方法完成，方法结果：" + obj);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	/**
	 * 反射工具类：Method类
	 */
	@Test
	public void test02() {
		// 获取Student类的Class实例对象
		Class<Student> clazz = Student.class;
		try {
			// 创建一个Student对象的实例
			Student stu0 = clazz.newInstance();
			stu0.setStuName("张三");
			// 获取Method工具类
			// 第一个参数是方法名，第二个参数是该方法对应的形参类型的列表
			Method method = clazz.getDeclaredMethod("doStuding", String.class, Date.class);
			// 使用Method类中的invoke方法，通过反射机制执行获取的方法对象
			/*
			 * invoke方法使用时，第一个参数是反射机制通过哪个实例对象去执行这个方法对象；
			 * 第二个是一个变长参数，需要和获取Method对象时所指定的形参列表保持对应关系； 返回值是方法对象执行的结果
			 */
			Object obj = method.invoke(stu0, "天津西青", new Date());
			System.out.println("反射执行方法完成，方法结果：" + obj);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	/**
	 * 反射工具类：Constructor类
	 */
	@Test
	public void test01() {
		// 3、Class类提供一个forName的静态方法(反射方式)，Class.forName()

		try {
			// 获取Class对象
			Class<Student> clazz = (Class<Student>) Class.forName("com.yuw.reflection.Student");
			// 获取构造方法对象
			Constructor<Student> constructor = clazz.getDeclaredConstructor(String.class, String.class, double.class);
			// 使用反射机制执行构造方法，获取一个实例对象
			// 执行构造方法时，传递的实参参数列表需要和获取构造方法时的参数列表一样
			Student stu0 = constructor.newInstance("张三", "男", 90);
			System.out.println("通过Constructor反射获取的Student类的实例对象：" + stu0);

			System.out.println("===========================");
			Student stu1 = clazz.newInstance();
			System.out.println("通过Class反射获取的Student类的实例对象：" + stu1);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
